home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / mem.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  39KB  |  1,658 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992,1993 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * mem.c:: routines for managing memory regions
  9.  */
  10.  
  11. #include "mint.h"
  12. #include "fasttext.h" /* for line A stuff */
  13.  
  14. #ifndef VgetSize
  15. extern long xbios();
  16. #define VgetSize(mode) xbios(91, (short)(mode))
  17. #define Vsetmode(mode) xbios(88, (short)(mode))
  18. #endif
  19.  
  20. static long core_malloc P_((long, int));
  21. static void core_free P_((long));
  22.  
  23. /* macro for testing whether a memory region is free */
  24. #define ISFREE(m) ((m)->links == 0)
  25.  
  26. /*
  27.  * list of shared text regions currently being executed
  28.  */
  29. SHTEXT *text_reg = 0;
  30.  
  31. /*
  32.  * initialize memory routines
  33.  */
  34.  
  35. /* initial number of memory regions */
  36. #define NREGIONS 512
  37.  
  38. /* number of new regions to allocate when the initial ones are used up */
  39. #define NEWREGIONS 256
  40.  
  41. static MEMREGION use_regions[NREGIONS+1];
  42. MEMREGION *rfreelist;
  43.  
  44. /* these variables are set in init_core(), and used in
  45.  * init_mem()
  46.  */
  47. static ulong scrnsize, scrnplace;
  48. static SCREEN *vscreen;
  49.  
  50. void
  51. init_mem()
  52. {
  53.     int i;
  54.     MEMREGION *r;
  55.     long newbase;
  56.  
  57.     use_regions[NREGIONS].next = 0;
  58.     for (i = 0; i < NREGIONS; i++) {
  59.         use_regions[i].next = &use_regions[i+1];
  60.     }
  61.     rfreelist = use_regions;
  62.  
  63.     init_core();
  64.     init_swap();
  65.  
  66.     init_tables();            /* initialize MMU constants */
  67.  
  68.     /* mark all the regions in the core & alt lists as "invalid" */
  69.     for (r = *core; r; r = r->next) {
  70.         mark_region(r,PROT_I);
  71.     }
  72.     for (r = *alt; r; r = r->next) {
  73.         mark_region(r,PROT_I);
  74.     }
  75.  
  76.     /* make sure the screen is set up properly */
  77.     newbase = s_realloc(scrnsize);
  78.  
  79.     /* if we did get a new screen, point the new screen
  80.      * at the right place after copying the data
  81.      * if possible, save the screen to another buffer,
  82.      * since if the new screen and old screen overlap
  83.      * the blit will look very ugly.
  84.      * Note that if the screen isn't moveable, then we set
  85.      * scrnsize to a ridiculously large value, and so the
  86.      * s_realloc above failed.
  87.      */
  88.     if (newbase) {
  89.     /* find a free region for temp storage */
  90.         for (r = *core; r; r = r->next) {
  91.             if (ISFREE(r) && r->len >= scrnsize)
  92.                 break;
  93.         }
  94.  
  95.         if (r) {
  96.             quickmove((char *)r->loc, (char *)scrnplace, scrnsize);
  97.             Setscreen((void *)r->loc, (void *)r->loc, -1);
  98.             Vsync();
  99.             quickmove((char *)newbase, (char *)r->loc, scrnsize);
  100.         } else {
  101.             quickmove((char *)newbase, (char *)scrnplace, scrnsize);
  102.         }
  103.         Setscreen((void *)newbase, (void *)newbase, -1);
  104.     /* fix the cursor */
  105.         Cconws("\r\n"); 
  106.     }
  107. }
  108.  
  109. /*
  110.  * init_core(): initialize the core memory map (normal ST ram) and also
  111.  * the alternate memory map (fast ram on the TT)
  112.  */
  113.  
  114. static MEMREGION *_core_regions = 0, *_alt_regions = 0,
  115.     *_ker_regions = 0;
  116.  
  117. MMAP core = &_core_regions;
  118. MMAP alt = &_alt_regions;
  119. MMAP ker = &_ker_regions;
  120.  
  121. /* note: add_region must adjust both the size and starting
  122.  * address of the region being added so that memory is
  123.  * always properly aligned
  124.  */
  125.  
  126. int
  127. add_region(map, place, size, mflags)
  128.     MMAP map;
  129.     ulong place, size;
  130.     unsigned mflags;    /* initial flags for region */
  131. {
  132.       MEMREGION *m;
  133.     ulong trimsize;
  134.  
  135.     TRACELOW(("add_region(map=%lx,place=%lx,size=%lx,flags=%x)",
  136.         map,place,size,mflags));
  137.  
  138.     m = new_region();
  139.     if (m == 0)
  140.         return 0;    /* failure */
  141.     m->links = 0;
  142.  
  143.     if (place & MASKBITS) {
  144.         /* increase place & shorten size by the amount we're trimming */
  145.         trimsize = (MASKBITS+1) - (place & MASKBITS);
  146.         if (size <= trimsize) goto lose;
  147.         size -= trimsize;
  148.         place += trimsize;
  149.     }
  150.  
  151.     /* now trim size DOWN to a multiple of pages */
  152.     if (size & MASKBITS) size &= ~MASKBITS;
  153.  
  154.     /* only add if there's anything left */
  155.     if (size) {
  156.         m->len = size;
  157.         m->loc = place;
  158.         m->next = *map;
  159.         m->mflags = mflags;
  160.         *map = m;
  161.     }
  162.     else {
  163.         /* succeed but don't do anything; dispose of region */
  164. lose:        dispose_region(m);
  165.     }
  166.     return 1;    /* success */
  167. }
  168.  
  169. static long
  170. core_malloc(amt, mode)
  171.     long amt;
  172.     int mode;
  173. {
  174.     static int mxalloc = -1;    /* does GEMDOS know about Mxalloc? */
  175.     long ret;
  176.  
  177.     if (mxalloc < 0) {
  178.         ret = (long)Mxalloc(-1L, 0);
  179.         if (ret == -32) mxalloc = 0;    /* unknown function */
  180.         else if (ret >= 0) mxalloc = 1;
  181.         else {
  182.             ALERT("GEMDOS returned %ld from Mxalloc", ret);
  183.             mxalloc = 0;
  184.         }
  185.     }
  186.     if (mxalloc)
  187.         return Mxalloc(amt, mode);
  188.     else if (mode == 1)
  189.         return 0L;
  190.     else
  191.         return Malloc(amt);
  192. }
  193.  
  194. static void
  195. core_free(where)
  196.     long where;
  197. {
  198.     Mfree((void *)where);
  199. }
  200.  
  201. void
  202. init_core()
  203. {
  204.     extern int FalconVideo;    /* set in main.c */
  205.     int scrndone = 0;
  206.     ulong size;
  207.     ulong place;
  208.     ulong temp;
  209.     void *tossave;
  210.  
  211.     tossave = (void *)core_malloc((long)TOS_MEM, 0);
  212.     if (!tossave) {
  213.         FATAL("Not enough memory to run MiNT");
  214.     }
  215.  
  216. /* initialize kernel memory */
  217.     place = (ulong)core_malloc(KERNEL_MEM, 3);
  218.     if (place != 0) {
  219.         nalloc_arena_add((void *)place,KERNEL_MEM);
  220.     }
  221.  
  222. /*
  223.  * find out where the screen is. We want to manage the screen
  224.  * memory along with all the other memory, so that Srealloc()
  225.  * can be used by the XBIOS to allocate screens from the
  226.  * end of memory -- this avoids fragmentation problems when
  227.  * changing resolutions.
  228.  */
  229. /* Note, however, that some graphics boards (e.g. Matrix)
  230.  * are unable to change the screen address. We fake out the
  231.  * rest of our code by pretending to have a really huge
  232.  * screen that can't be changed.
  233.  */
  234.     scrnplace = (long)Physbase();
  235.  
  236.     vscreen = (SCREEN *)((char *)lineA0() - 346);
  237.     if (FalconVideo) {
  238.     /* the Falcon can tell us the screen size */
  239.         scrnsize = VgetSize(Vsetmode(-1));
  240.     } else {
  241.     /* otherwise, use the line A variables */
  242.         scrnsize = (vscreen->maxy+1)*(long)vscreen->linelen;
  243.     }
  244.  
  245. /* check for a graphics card with fixed screen location */
  246. #define phys_top_st (*(ulong *)0x42eL)
  247.  
  248.     if (scrnplace >= phys_top_st) {
  249. /* screen isn't in ST RAM */
  250.         scrnsize = 0x7fffffffUL;
  251.         scrndone = 1;
  252.     } else {
  253.         temp = (ulong)core_malloc(scrnsize+256L, 0);
  254.         if (temp) {
  255.             (void)Setscreen((void *)-1L,
  256.                     (void *)((temp+511)&(0xffffff00L)), -1);
  257.             if ((long)Physbase() != (temp+511)&(0xffffff00L)) {
  258.                 scrnsize = 0x7fffffffUL;
  259.                 scrndone = 1;
  260.             }
  261.             (void)Setscreen((void *)-1L, (void *)scrnplace, -1);
  262.             core_free(temp);
  263.         }
  264.     }
  265.  
  266. /* initialize ST RAM */
  267.     size = (ulong)core_malloc(-1L, 0);
  268.     while (size > 0) {
  269.         place = (ulong)core_malloc(size, 0);
  270.         if (place + size == scrnplace) {
  271.             size += scrnsize;
  272.             scrndone = 1;
  273.         }
  274.         if (!add_region(core, place, size, M_CORE))
  275.             FATAL("init_mem: unable to add a region");
  276.         size = (ulong)core_malloc(-1L, 0);
  277.     }
  278.  
  279.     if (!scrndone) {
  280.         (void)add_region(core, scrnplace, scrnsize, M_CORE);
  281.     }
  282.  
  283. /* initialize alternate RAM */
  284.     size = (ulong)core_malloc(-1L, 1);
  285.     while (size > 0) {
  286.         place = (ulong)core_malloc(size, 1);
  287.         if (!add_region(alt, place, size, M_ALT))
  288.             FATAL("init_mem: unable to add a region");
  289.         size = (ulong)core_malloc(-1L, 1);
  290.     }
  291.  
  292.     (void)Mfree(tossave);        /* leave some memory for TOS to use */
  293. }
  294.  
  295. /*
  296.  * init_swap(): initialize the swap area; for now, this does nothing
  297.  */
  298.  
  299. MEMREGION *_swap_regions = 0;
  300. MMAP swap = &_swap_regions;
  301.  
  302. void
  303. init_swap()
  304. {
  305. }
  306.  
  307. /*
  308.  * routines for allocating/deallocating memory regions
  309.  */
  310.  
  311. /*
  312.  * new_region returns a new memory region descriptor, or NULL
  313.  */
  314.  
  315. MEMREGION *
  316. new_region()
  317. {
  318.     MEMREGION *m, *newfrees;
  319.     int i;
  320.  
  321.     m = rfreelist;
  322.     if (!m) {
  323.         ALERT("new_region: ran out of free regions");
  324.         return 0;
  325.     }
  326.     assert(ISFREE(m));
  327.     rfreelist = m->next;
  328.     m->next = 0;
  329.  
  330. /* if we're running low on free regions, allocate some more
  331.  * we have to do this with at least 1 free region left so that get_region
  332.  * has a chance of working
  333.  */
  334.     if (rfreelist && !rfreelist->next) {
  335.         MEMREGION *newstuff;
  336.  
  337.         TRACELOW(("get_region: getting new region descriptors"));
  338.         newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
  339.         if (!newstuff)
  340.             newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
  341.         if (!newstuff)
  342.             newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION